package cn.sumpu.app.guoguojie.util;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.ImageIcon;

import cn.sumpu.app.guoguojie.exception.AppBusinessException;

public class ImageUtil {

	private static final boolean USE_TRANSFORM = false;

	/**
	 * @param srcImgPath 要被切割的图像地址
	 * @param descDir 要保存图像的地址
	 * @param imageName 保存图片的名称
	 * @param x 要切割的图片的在原图片的x坐标
	 * @param y 要切割的图片的在原图片的y坐标
	 * @param destWidth 要切割图片的宽度
	 * @param destHeight 要切割图片的高度
	 * @param divWidth 要切割图片的分辨率的宽度
	 * @param divHeight 客户端原图片外层的高度
	 * @param tagWidth 要切割图片的分辨率的宽度
	 * @param tagHeight 要切割图片的分表率的高度
	 * @return
	 * @throws AppBusinessException
	 */
	public static String cut(String srcImgPath, String descDir,String imageName, int x, int y,
			int destWidth, int destHeight,int divWidth,int divHeight,int tagWidth,int tagHeight)  throws AppBusinessException{
		try {
			Image img;
			ImageFilter cropFilter;
			BufferedImage bi = ImageIO.read(new File(srcImgPath));
			int srcWidth = bi.getWidth();
			int srcHeight = bi.getHeight();
			
			double zoom = (double)srcWidth / divWidth;
			double zoomHeight = (double)srcHeight / divHeight;
			if(zoomHeight > zoom){
				zoom = zoomHeight;
			}
			if(destWidth==0 || destHeight==0){
				destWidth = divWidth;
				destHeight = divHeight;
			}
			int tmpTagWidth = (int)(destWidth*zoom);
			int tmpTagHeight = (int)(destHeight*zoom);
			if(tmpTagWidth < tagWidth && tmpTagHeight < tagHeight){
				tagWidth = tmpTagWidth;
				tagHeight = tmpTagHeight;
			}
			cropFilter = new CropImageFilter((int)(x * zoom),(int) (y * zoom), (int)(destWidth*zoom), (int)(destHeight*zoom));
			img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(bi.getSource(), cropFilter));
			
			BufferedImage tag = new BufferedImage(tagWidth, tagWidth,BufferedImage.TYPE_INT_RGB);
			Graphics g = tag.getGraphics();
			g.drawImage(img, 0, 0,tagWidth,tagWidth, null);
			g.dispose();
			File f = new File(descDir);
			if (!f.exists()) {
				f.mkdirs();
			}
			ImageIO.write(tag, "JPEG", new File(descDir + imageName+ "_" + tagWidth + "_" + tagHeight + ".jpg"));
			return "_" + tagWidth + "_" + tagHeight + ".jpg";
		} catch (Exception e) {
			e.printStackTrace();
			throw  new AppBusinessException("切割头像失败",e);
		}
	}

	public static String makeThumbnail(String srcImgPath,
			Map<String, Object> settings) {
		int tw = (Integer) settings.get("thumbnailWidth");
		int th = (Integer) settings.get("thumbnailHeight");
		int maxtw = (Integer) settings.get("maxThumbnailWidth");
		int maxth = (Integer) settings.get("maxThumbnailHeight");
		return makeThumbnail(srcImgPath, tw, th, maxtw, maxth);
	}

	public static String makeThumbnail(String srcImgPath, int thumbnailWidth, int thumbnailHeight,
			int maxThumbnailWidth, int maxThumbnailHeight) {
		File srcFile = new File(srcImgPath);
		if (!srcFile.exists()) {
			return null;
		}
		String destPath = srcImgPath + "_thumb.jpg";
		File destFile = new File(destPath);
		if (thumbnailWidth < 60) {
			thumbnailWidth = 60;
		}
		if (thumbnailHeight < 60) {
			thumbnailHeight = 60;
		}
		boolean make_max = false;
		if (maxThumbnailWidth >= 300 && maxThumbnailHeight >= 300) {
			make_max = true;
		}
		String srcImgType = getImageType(srcFile);
		if ("gif".equals(srcImgType)) {
			make_max = false;
		}
		try {
			BufferedImage srcImg = ImageIO.read(srcFile);
			float src_w = srcImg.getWidth();
			float src_h = srcImg.getHeight();
			if (src_w <= maxThumbnailWidth && src_h <= maxThumbnailHeight)
				make_max = false;
			float thumb_ratio = thumbnailWidth / thumbnailHeight;
			float src_ratio = src_w / src_h;
			if (thumb_ratio <= src_ratio) {
				thumbnailHeight = (int) (thumbnailWidth / src_ratio);
				maxThumbnailHeight = (int) (maxThumbnailWidth * (src_h / src_w));
			} else {
				thumbnailWidth = (int) (thumbnailHeight * src_ratio);
				maxThumbnailWidth = (int) (maxThumbnailHeight * (src_w / src_h));
			}
			if (src_w > thumbnailWidth || src_h > thumbnailHeight) {
				double x_ratio = (double) thumbnailWidth / src_w;
				double y_ratio = (double) thumbnailHeight / src_h;
				AffineTransform tx = new AffineTransform();
				tx.setToScale(x_ratio, y_ratio);
				BufferedImage thumbImg = new BufferedImage(thumbnailWidth, thumbnailHeight,
						BufferedImage.TYPE_3BYTE_BGR);
				Graphics2D g2d = thumbImg.createGraphics();
				if (USE_TRANSFORM) {
					g2d.drawImage(srcImg, tx, null);
				} else {
					Image scaleImg = getScaledInstance(srcImg, thumbnailWidth, thumbnailHeight);
					g2d.drawImage(scaleImg, 0, 0, null);
				}
				g2d.dispose();
				ImageIO.write(thumbImg, "jpeg", destFile);
				if (make_max) {
					BufferedImage maxImg = new BufferedImage(maxThumbnailWidth, maxThumbnailHeight,
							BufferedImage.TYPE_3BYTE_BGR);
					g2d = maxImg.createGraphics();
					if (USE_TRANSFORM) {
						g2d.drawImage(srcImg, tx, null);
					} else {
						Image scaleImg = getScaledInstance(srcImg, maxThumbnailWidth, maxThumbnailHeight);
						g2d.drawImage(scaleImg, 0, 0, null);
					}
					g2d.dispose();
					ImageIO.write(maxImg, "jpeg", srcFile);
				}
			}
		} catch (IOException e) {
			return null;
		}
		return destFile.exists() ? destPath : null;
	}

	public static void makeWatermark(String waterText, String targetImg,
			Font font, Color color, int watermarkPos) {
		try {
			File srcFile = new File(targetImg);
			String srcImgType = getImageType(srcFile);
			if (srcImgType.equals("gif")) {
				byte[] bytes = new byte[1024];
				FileInputStream fis = new FileInputStream(targetImg);
				fis.read(bytes);
				String srcContent = new String(bytes, "UTF-8");
				if (srcContent.indexOf("NETSCAPE2.0") != -1) {
					return;
				}
			}
			Image src = ImageIO.read(srcFile);
			int src_w = src.getWidth(null);
			int src_h = src.getHeight(null);
			BufferedImage image = new BufferedImage(src_w, src_h,
					BufferedImage.TYPE_INT_RGB);
			Graphics2D g2d = image.createGraphics();
			g2d.drawImage(src, 0, 0, src_w, src_h, null);
			g2d.setComposite(AlphaComposite.getInstance(
					AlphaComposite.SRC_ATOP, 0.7f));
			g2d.setColor(color);
			g2d.setFont(font);
			FontRenderContext frc = g2d.getFontRenderContext();
			Rectangle2D rect = font.getStringBounds(waterText, frc);
			int water_w = (int) rect.getWidth();
			int water_h = (int) rect.getHeight();
			if ((src_w < water_w + 150) || (src_h < water_h + 150)) {
				return;
			}
			int x = 0, y = 0;
			switch (watermarkPos) {
			case 1:
				x = 0;
				y = 0;
				break;
			case 2:
				x = src_w - water_w;
				y = 0;
				break;
			case 3:
				x = 0;
				y = src_h - water_h;
				break;
			case 4:
				x = src_w - water_w;
				y = src_h - water_h;
				break;
			default:
				x = Common.rand(0, src_w - water_w);
				y = Common.rand(0, src_h - water_h);
			}
			g2d.drawString(waterText, x, y);
			g2d.dispose();
			ImageIO.write(image, srcImgType, srcFile);
		} catch (IOException e) {
			return;
		}
	}

	public static void makeWatermark(String waterImg, String targetImg,
			int watermarkPos) {
		try {
			File srcFile = new File(targetImg);
			String srcImgType = getImageType(srcFile);
			if (srcImgType.equals("gif")) {
				byte[] bytes = new byte[1024];
				FileInputStream fis = new FileInputStream(targetImg);
				fis.read(bytes);
				String srcContent = new String(bytes, "UTF-8");
				if (srcContent.indexOf("NETSCAPE2.0") != -1) {
					return;
				}
			}
			String watermark = waterImg;
			Image water = ImageIO.read(new File(watermark));
			Image src = ImageIO.read(srcFile);
			int water_w = water.getWidth(null);
			int water_h = water.getHeight(null);
			int src_w = src.getWidth(null);
			int src_h = src.getHeight(null);
			if ((src_w < water_w + 150) || (src_h < water_h + 150)) {
				return;
			}
			int x = 0, y = 0;
			switch (watermarkPos) {
			case 1:
				x = 0;
				y = 0;
				break;
			case 2:
				x = src_w - water_w;
				y = 0;
				break;
			case 3:
				x = 0;
				y = src_h - water_h;
				break;
			case 4:
				x = src_w - water_w;
				y = src_h - water_h;
				break;
			default:
				x = Common.rand(0, src_w - water_w);
				y = Common.rand(0, src_h - water_h);
			}
			BufferedImage image = new BufferedImage(src_w, src_h,
					BufferedImage.TYPE_INT_RGB);
			Graphics2D g2d = image.createGraphics();
			g2d.drawImage(src, 0, 0, src_w, src_h, null);
			g2d.setComposite(AlphaComposite.getInstance(
					AlphaComposite.SRC_ATOP, 0.7f));
			g2d.drawImage(water, x, y, water_w, water_h, null);
			g2d.dispose();
			ImageIO.write(image, srcImgType, srcFile);
		} catch (IOException e) {
			return;
		}
	}

	public static String getImageType(File imgFile) {
		String imageType = null;
		try {
			ImageInputStream iis = ImageIO.createImageInputStream(imgFile);
			Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
			if (iter.hasNext()) {
				ImageReader reader = iter.next();
				imageType = reader.getFormatName().toLowerCase();
			}
			iis.close();
		} catch (IOException e) {
		}
		return imageType;
	}

	private static Image getScaledInstance(BufferedImage srcImage,
			int imageWidth, int imageHeight) {
		ImageFilter filter = new java.awt.image.AreaAveragingScaleFilter(
				imageWidth, imageHeight);
		ImageProducer prod = new FilteredImageSource(srcImage.getSource(),
				filter);
		Image newImage = Toolkit.getDefaultToolkit().createImage(prod);
		ImageIcon imageIcon = new ImageIcon(newImage);
		Image scaleImg = imageIcon.getImage();
		return scaleImg;
	}
}
